package com.chinairi.mall.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinairi.common.annotation.DoPage;
import com.chinairi.common.utils.RedisUtil;
import com.chinairi.common.utils.UserSession;
import com.chinairi.mall.config.ValidationResult;
import com.chinairi.mall.config.ValidatorImpl;
import com.chinairi.mall.constant.CiccTableNameEnum;
import com.chinairi.mall.controller.viewobject.ApproveDbIdVO;
import com.chinairi.mall.controller.viewobject.GoodsInfoVO;
import com.chinairi.mall.dao.*;
import com.chinairi.mall.error.BusinessException;
import com.chinairi.mall.error.EmBusinessError;
import com.chinairi.mall.model.*;
import com.chinairi.mall.service.IGoodsInfoService;
import com.chinairi.mall.service.modelobject.*;
import com.chinairi.mall.util.CiccRecordUtil;
import com.chinairi.mall.util.ExcelUploadDataListenerUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 供应商查看商品的一些基本信息和一些维护功能，比如上下架，起订量的设置
 * //供应商上架表
 * //供应 服务实现类
 * </p>
 *
 * @author Webgasd
 * @since 2020-09-12
 */
@Service
public class GoodsInfoServiceImpl extends ServiceImpl<GoodsInfoMapper, GoodsInfo> implements IGoodsInfoService {
    @Autowired
    private GoodsInfoMapper goodsInfoMapper;
    @Autowired
    private GoodsFeatureValueMapper goodsFeatureValueMapper;
    @Autowired
    private GoodsPictureMapper goodsPictureMapper;
    @Autowired
    private CompShopMapper compShopMapper;
    @Autowired
    private MaterialServiceImpl materialService;
    @Autowired
    private ValidatorImpl validator;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private UserCompanyInfoServiceImpl userCompanyInfoService;
    @Autowired
    private MaterialMapper materialMapper;
    @Autowired
    private ContractMatMapper contractMatMapper;
    @Autowired
    private OrderInfoMapper orderInfoMapper;


    public String getMaterialName(String matDbId) {
        Map<Object, Object> materialMapResult = redisUtil.hmget("materialMap");
        if (materialMapResult.isEmpty() || materialMapResult.get(matDbId) == null) {
            materialService.putRedis();
        }
        return (String) redisUtil.hmget("materialMap").get(matDbId);
    }

    /**
     * 搜索商品
     * 按商品名称、物料编码、上架状态、审核状态查询
     *
     * @param type
     * @param request
     */
    @Override
    public String getCsDbid(String type, HttpServletRequest request) {
        CompShop compShop = compShopMapper.getByType(type, UserSession.getUserId());
        if (compShop == null) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "您暂时没有店铺，请先申请店铺！");
        }
        return compShop.getCsDbid();
    }

    /**
     * 获取店铺下的商品列表
     *
     * @param goodsInfoVO
     * @param csDbId
     * @return
     */
    @DoPage
    @Override
    public List<GoodsInfo> getListByCsDbId(GoodsInfoVO goodsInfoVO, String csDbId) {
        QueryWrapper<GoodsInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .like(StringUtils.isNotEmpty(goodsInfoVO.getGoodsName()), "GOODS_NAME", goodsInfoVO.getGoodsName())
                .eq(goodsInfoVO.getGoodsShelfState() != null, "GOODS_SHELF_STATE", goodsInfoVO.getGoodsShelfState())
                .like(StringUtils.isNotEmpty(goodsInfoVO.getGoodsDbid()), "GOODS_DBID", goodsInfoVO.getGoodsDbid())
                .eq(goodsInfoVO.getGoodsApproveStatus() != null, "GOODS_APPROVE_STATUS", goodsInfoVO.getGoodsApproveStatus())
                .eq(StringUtils.isNotEmpty(csDbId), "CS_DBID", csDbId)
                .orderByAsc("GOODS_SHELF_STATE")
                .orderByDesc("GOODS_CREATE_TIME");
        List<GoodsInfo> list = this.list(queryWrapper);
        if (list != null && !list.isEmpty()) {
            list.forEach(goodsInfo -> {
                CiccRecord ciccRecord = CiccRecordUtil.getCiccRecord(CiccTableNameEnum.GOODS_STATUS.getCodeValue(), String.valueOf(goodsInfo.getGoodsApproveStatus()));
                goodsInfo.setGoodsApproveStatusLabel(ciccRecord.getLabel());
            });
        }
        return list;
    }

    /**
     * 添加一条商品信息
     *
     * @param goodsInfoVO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(GoodsInfoVO goodsInfoVO) {
        ValidationResult result = validator.validate(goodsInfoVO);
        if (result.isHashErrors()) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, result.getErrMsg());
        }
        String goodsDbid = UUID.randomUUID().toString().replace("-", "");
        goodsInfoVO.setGoodsDbid(goodsDbid);
        //设置默认状态，0未上架
        goodsInfoVO.setGoodsShelfState(0);
        goodsInfoVO.setGoodsSetVisible(1);
        goodsInfoVO.setGoodsApproveStatus(0);
        //插入商品表
        goodsInfoMapper.insert(goodsInfoVO);
        batchDelete(goodsDbid);
        batchInsertFeature(goodsInfoVO.getGoodsFeatureValueList(), goodsDbid);
        batchInsertPic(goodsInfoVO.getGoodsPictureList(), goodsDbid);
    }

    /**
     * 更新商品信息
     *
     * @param goodsInfoVO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateGoods(GoodsInfoVO goodsInfoVO) {

        ValidationResult result = validator.validate(goodsInfoVO);
        if (result.isHashErrors()) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, result.getErrMsg());
        }
        goodsInfoVO.setGoodsShelfState(0);
        goodsInfoVO.setGoodsSetVisible(1);
        goodsInfoVO.setGoodsApproveStatus(0);
        //更新商品基本信息
        goodsInfoMapper.updateById(goodsInfoVO);
        batchDelete(goodsInfoVO.getGoodsDbid());
        batchInsertFeature(goodsInfoVO.getGoodsFeatureValueList(), goodsInfoVO.getGoodsDbid());
        batchInsertPic(goodsInfoVO.getGoodsPictureList(), goodsInfoVO.getGoodsDbid());
    }

    @Transactional(rollbackFor = Exception.class)
    public void batchInsertPic(List<GoodsPicture> goodsPictureList, String goodsDbid) {
        if (goodsPictureList.size() > 0) {
            goodsPictureMapper.batchInsert(goodsPictureList.stream().peek(list -> {
                list.setGoodsPicDbid(list.getGoodsPicDbid() == null ? UUID.randomUUID().toString().replace("-", "") : list.getGoodsPicDbid());
                list.setGoodsDbid(goodsDbid);
            }).collect(Collectors.toList()));
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void batchInsertFeature(List<GoodsFeatureValue> goodsFeatureValueList, String goodsDbid) {
        //获取前端传来的特征值对象
        if (goodsFeatureValueList.size() > 0) {
            //批量插入特征值
            goodsFeatureValueMapper.batchInsert(goodsFeatureValueList.stream().peek(list -> {
                list.setGooFeaValDbid(list.getGooFeaValDbid() == null ? UUID.randomUUID().toString().replace("-", "") : list.getGooFeaValDbid());
                list.setGoodsDbid(goodsDbid);
                list.setGfvCreateUser(list.getGfvCreateUser() == null ? UserSession.getUserId() : list.getGfvCreateUser());
                list.setGfvCreateTime(list.getGfvCreateTime() == null ? new Date() : list.getGfvCreateTime());
                list.setGfvUpdateUser(UserSession.getUserId());
                list.setGfvUpdateTime(new Date());
            }).collect(Collectors.toList()));
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void batchDelete(String id) {
        //删除此商品原有的特征值和特征量
        QueryWrapper<GoodsFeatureValue> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("GOODS_DBID", id);
        goodsFeatureValueMapper.delete(wrapper1);
        //删除原有图片
        QueryWrapper<GoodsPicture> pictureQueryWrapper = new QueryWrapper<>();
        pictureQueryWrapper.eq("GOODS_DBID", id);
        goodsPictureMapper.delete(pictureQueryWrapper);
    }

    /**
     * 删除商品
     *
     * @param goodsDbid
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(String goodsDbid) {
        goodsInfoMapper.deleteById(goodsDbid);
    }

    /**
     * 根据供应商主键获取合同列表
     *
     * @return
     */
    @Override
    public List<ViewContractMatRelMO> getContractList(String flag) {
        return goodsInfoMapper.getContractList(UserSession.getUserId(), flag);
    }


    /**
     * 获取合同下的物料
     *
     * @param contDbid
     * @return
     */
    @Override
    public List<GoodsInfoVO> getByContDbid(String contDbid) {
        return goodsInfoMapper.selectByContDbid(contDbid);
    }

    /**
     * 根据dbid获取商品信息
     *
     * @param id
     * @return
     */
    @Override
    public GoodsInfoVO getByDbid(String id) {
        GoodsInfoVO goodsInfoVO = goodsInfoMapper.selectByDbId(id);
        Map<String, Object> map = new HashMap<>(1);
        map.put("GOODS_DBID", id);
        List<GoodsFeatureValue> goodsFeatureValueList = goodsFeatureValueMapper.selectByMap(map);
        List<GoodsPicture> goodsPictureList = goodsPictureMapper.selectByMap(map);
        goodsInfoVO.setGoodsFeatureValueList(goodsFeatureValueList);
        goodsInfoVO.setGoodsPictureList(goodsPictureList);
        //获取这个商品所在店铺及企业信息
        String csDbId = goodsInfoVO.getCsDbid();
        ShopInfoToCompRedisMO shopInfoToCompRedisMO = userCompanyInfoService.getShopInfoToCompFromRedis(csDbId);
        if (shopInfoToCompRedisMO != null) {
            goodsInfoVO.setShopName(shopInfoToCompRedisMO.getCsShopName());
            goodsInfoVO.setUciCompName(shopInfoToCompRedisMO.getUciCompName());
            goodsInfoVO.setShopIntroduction(shopInfoToCompRedisMO.getCsShopIntroduction());
            goodsInfoVO.setContactMan(shopInfoToCompRedisMO.getUciRepresentative());
            goodsInfoVO.setBusinessAddress(shopInfoToCompRedisMO.getUciBusinessAddress());
            goodsInfoVO.setContactPhone(shopInfoToCompRedisMO.getUciTelphone());
        }
        return goodsInfoVO;
    }

    /**
     * 根据物料的dbId获取商品和供应商所有的信息
     *
     * @param dbIdList 物料dbIdList
     * @return List
     */
    @Override
    public Map<String, List<GoodsAllInfoByMatDbIdMO>> selectAllInfoByMatDbId(List<String> dbIdList) {
        if (dbIdList.size() == 0) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "请求物料编码组为空");
        }
        List<GoodsAllInfoByMatDbIdMO> goodsAllInfoByMatDbIdMoList = goodsInfoMapper.selectAllInfoByMatDbId(dbIdList);
        if (goodsAllInfoByMatDbIdMoList.size() == 0) {
            return null;
        }
        Map<String, List<GoodsAllInfoByMatDbIdMO>> resultMap = new HashMap<>(dbIdList.size());
        for (String dbId : dbIdList) {
            GoodsAllInfoByMatDbIdMO bean = new GoodsAllInfoByMatDbIdMO();
            resultMap.put(dbId, new ArrayList<GoodsAllInfoByMatDbIdMO>(1));
            bean.setMatDbid(dbId);
            bean.setMatName(getMaterialName(dbId));
            resultMap.get(dbId).add(bean);
        }
        for (GoodsAllInfoByMatDbIdMO goodsAllInfoByMatDbIdMo : goodsAllInfoByMatDbIdMoList) {
            resultMap.get(goodsAllInfoByMatDbIdMo.getMatDbid()).add(goodsAllInfoByMatDbIdMo);
        }
        return resultMap;
    }

    /**
     * 批量提交商品审核
     *
     * @param approveDbIdVoList
     */
    @Override
    public void updateStatus(List<ApproveDbIdVO> approveDbIdVoList) {
        //获取前端传来的特征值对象
        if (approveDbIdVoList.size() > 0) {
            List<GoodsInfo> goodsInfoList = new ArrayList<>();
            for (ApproveDbIdVO approveDbIdVo : approveDbIdVoList) {
                GoodsInfo goodsInfo = new GoodsInfo();
                goodsInfo.setGoodsDbid(approveDbIdVo.getDbId());
                if (approveDbIdVo.getType() == 1) {
                    goodsInfo.setGoodsShelfState(1);
                } else if (approveDbIdVo.getType() == 3) {
                    goodsInfo.setGoodsShelfState(3);
                }
                goodsInfo.setGoodsApproveStatus(3);
                goodsInfoList.add(goodsInfo);
            }
            //批量插入特征值
            goodsInfoMapper.batchUpdateStatus(goodsInfoList);
        }
    }

    /**
     * 获取首页商品列表
     * 搜索条件为：
     * goodsName  商品名称     全模糊搜索
     * matCode    物料类别编码  左起始搜索  主要是侧边栏进入后使用
     * csShopName 店铺名称     全模糊搜索
     *
     * @param homeGoodsMo
     * @return
     */
    @Override
    @DoPage
    public List<HomeGoodsMO> getHomeGoods(HomeGoodsMO homeGoodsMo) {
        return goodsInfoMapper.selectHomeGoods(homeGoodsMo);
    }

    /**
     * 获取商品列表
     *
     * @param homeGoodsMo@return
     */
    @Override
    @DoPage
    public List<HomeGoodsMO> getGoodsListByCsDbId(HomeGoodsMO homeGoodsMo) {
        return goodsInfoMapper.getGoodsListByCsDbId(homeGoodsMo);
    }

    /**
     * 获取热销商品
     *
     * @return
     */
    @Override
    public List<HomeGoodsMO> getHotSaleGoods() {
        return goodsInfoMapper.selectHotSaleGoodList();
    }

    /**
     * 导入excel商品数据
     *
     * @param file
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void uploadFile(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), GoodsInfoMO.class, new ExcelUploadDataListenerUtil(goodsInfoMapper, materialMapper, contractMatMapper, compShopMapper)).sheet().doRead();
    }

    /**
     * 获取商品信息上传模板
     *
     * @return
     */
    @Override
    public void getModel(HttpServletResponse response) throws IOException {
        String fileName = "商品信息上传模板.xlsx";
        fileName = URLEncoder.encode(fileName, "UTF-8");
        response.setCharacterEncoding("utf8");
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        response.setHeader("Pragma", "public");
        response.setHeader("Cache-Control", "no-store");
        response.addHeader("Cache-Control", "max-age=0");
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("templates/excel/goodsModel.xlsx");
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).build();
        excelWriter.finish();
    }


}
